Skip to content

fix: A draft site no longer opens to a user whose name ends its owner's EXO-91427 - #1356

Merged
boubaker merged 1 commit into
developfrom
backport/EXO-91427-draft-owner-exact-suffix
Oct 27, 2026
Merged

boubaker merged 1 commit into
developfrom
backport/EXO-91427-draft-owner-exact-suffix

Conversation

@boubaker

Copy link
Copy Markdown
Member

Symptom: a user whose username ends another user's after an _ (john for doe_john) could open that user's draft site (<type>_<name>_draft_doe_john), at its URL and in the site layout editor, and change or delete it.

Cause: the DRAFT branches of UserACL#hasEditPermission and UserACL#hasAccessPermission(…, Stream) granted a draft site whose name ended with "_" + userId. Usernames admit _ and so do site names, so a draft's name does not tell its owner: john's draft of a site named team_draft and draft_john's draft of team are both portal_team_draft_draft_john.

Fix: every suffix following a _draft_ of the name is a candidate owner. The identity is granted the draft only when it is one of them and no other candidate is an existing user (UserHandler#findUserByName(…, UserStatus.ANY)). A candidate the user store cannot check refuses the draft, and a name holding a single _draft_ needs no lookup. Administrators keep their access to every draft. UserACLTest pins the owner, the suffix user with the owner existing and deleted, a site manager of the drafted site, both ambiguous cases, a failed lookup, an administrator and an anonymous caller.

Meeds-io/layout#590 refuses to create a draft whose name another existing user could own, and removes a deleted user's draft sites. Until it is merged, and for users deleted before it, a draft whose other candidate owner was deleted is granted to the remaining one, as it was before this change. Merge this PR first: #590's check relies on this rule.

Knowledge: Meeds-io/eng-standards#522

This change is classified N1 (ACL and identity resolution in UserACL): its approver must be an Archi/Dev who knows it is N1, not an approval on AI review alone, and author ≠ approver.

🤖 Generated with Claude Code

Base automatically changed from backport/EXO-91299-entitymanager-exceptions to develop October 27, 2026 12:18
EXO-91427 (#1345)

**Symptom**: a user whose username ends another user's after an `_`
(`john` for `doe_john`) could open that user's draft site
(`<type>_<name>_draft_doe_john`), at its URL and in the site layout
editor, and change or delete it.

**Cause**: the `DRAFT` branches of `UserACL#hasEditPermission` and
`UserACL#hasAccessPermission(…, Stream)` granted a draft site whose name
ended with `"_" + userId`. Usernames admit `_` and so do site names, so
a draft's name does not tell its owner: `john`'s draft of a site named
`team_draft` and `draft_john`'s draft of `team` are both
`portal_team_draft_draft_john`.

**Fix**: every suffix following a `_draft_` of the name is a candidate
owner. The identity is granted the draft only when it is one of them and
no other candidate is an existing user (`UserHandler#findUserByName(…,
UserStatus.ANY)`). A candidate the user store cannot check refuses the
draft, and a name holding a single `_draft_` needs no lookup.
Administrators keep their access to every draft. `UserACLTest` pins the
owner, the suffix user with the owner existing and deleted, a site
manager of the drafted site, both ambiguous cases, a failed lookup, an
administrator and an anonymous caller.

Meeds-io/layout#590 refuses to create a draft whose name another
existing user could own, and removes a deleted user's draft sites. Until
it is merged, and for users deleted before it, a draft whose other
candidate owner was deleted is granted to the remaining one, as it was
before this change. Merge this PR first: #590's check relies on this
rule.

Knowledge: Meeds-io/eng-standards#522

This change is classified N1 (ACL and identity resolution in `UserACL`):
its approver must be an Archi/Dev who knows it is N1, not an approval on
AI review alone, and author ≠ approver.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 3fd575f)
@boubaker
boubaker force-pushed the backport/EXO-91427-draft-owner-exact-suffix branch from e342683 to c8f5702 Compare October 27, 2026 12:21
@boubaker
boubaker requested a review from ahamdi October 27, 2026 12:21
@boubaker

Copy link
Copy Markdown
Member Author

Backport evidence

Source: #1345, squash-merged into feature/maintenance. Its change is on origin/feature/maintenance at 3fd575ffd7 (matched against the branch's current head, 2026-10-27). The PO validated it on the maintenance acceptance server on 2026-10-27.

Picks: c8f5702acb = git cherry-pick -x 3fd575ffd7, on origin/develop (df7956bfc2).

Rebase: the pick was made on the EXO-91299 backport branch, then rebased onto develop when that branch squash-merged as #1355: e342683863 → c8f5702acb, base 57125d9f5d → df7956bfc2. The rebase was clean.

Adaptations: none. The pick applied cleanly, and no commit was added.

Verification

  • git show -U0 <pick> | git patch-id --stable gives the same result on c8f5702acb and on 3fd575ffd7: e61f8f9bec87. It was unchanged by the rebase.
  • gh pr diff 1345 | git patch-id --stable equals git show c8f5702acb | git patch-id --stable: adeb2a6ca1f3.
  • The source's approval is on its head: APPROVED by ahamdi at de4674777c, which is the source PR's head.
  • mvn -B -ntp -Dcheckstyle.skip=true -pl component/portal -am install at e342683863: Tests run: 453, Failures: 0, Errors: 0, Skipped: 0, BUILD SUCCESS. That is the count the source reports for component/portal. e342683863 and the head c8f5702acb have the same tree (85512bd4efdb): the base fix: Throw the EntityManager's own exception from the kernel DAOs' proxy - EXO-91299 #1355 merged is the same change as the pick it was built on.
  • Merge order: after fix: Throw the EntityManager's own exception from the kernel DAOs' proxy - EXO-91299 #1355, which has merged. Before the stacked Meeds-io/portal EXO-91183 backport.

Level: N1, restated from the source. A backport from feature/maintenance whose every pick's patch-id equals its source's diff merges on its first approval (ai-review-and-merge.md §3). It lands by squash, with the source's body as its message.

@sonarqubecloud

Copy link
Copy Markdown

@boubaker
boubaker merged commit 0e6e3d5 into develop Oct 27, 2026
13 checks passed
@boubaker
boubaker deleted the backport/EXO-91427-draft-owner-exact-suffix branch October 27, 2026 12:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants